#!/usr/bin/env python

import optparse
import os
import subprocess
import tempfile
import warnings

from charmicat import BadCommandLineError

from csbbelle import BASFScript

default_pars = {'outpath_stub': None,
                'inpath': None,
                }

def main():
    '''
    cmix_basf.py [opts] module file.mdst [file.mdst [...]]

    Runs BASF with the standard options using the analysis module `module' 
    on `input_file [input_file [...]]'
    '''

    op = optparse.OptionParser(usage=main.__doc__)

    op.add_option("-n", "--nevents", dest='nevents', type='int', default=0,
                  help='Process N events and quit', metavar='N')
    op.add_option("--hbook", dest='hbook', action='store_true', default=False, 
                  help='Write HBOOK output')
    op.add_option("--nocrash", dest='nocrash', action='store_true', 
                  default=False, 
                  help='Use libs that prevent crashes on incomplete MDST')
    op.add_option("-p", "--parameter", dest='basf_pars', action='append', 
                  default=[], help='Push parameter NAME=VALUE to BASF input', 
                  metavar='NAME=VALUE')                  
    op.add_option("-w", "--write", dest='write', default=None, 
                  help='Write BASF script to PATH', metavar='PATH')
    op.add_option("--no-default-pars", dest='no_default_pars', 
                  action='store_true', default=False,
                  help=("Don't insert default parameters ({}) " +
                        "into BASF input").format(default_pars.keys()))

    opts, args = op.parse_args()

    if len(args) == 0:
        msg = "Please supply a module name and at least one MDST file."
        raise BadCommandLineError(msg, -1)

    basfmod = args.pop(0)

    if len(args) == 0:
        msg = "Please supply at least one MDST file."
        raise BadCommandLineError(msg, -2)

    mdst_files = args[:]

    basf_pars = {}

    if len(opts.basf_pars) > 0:
        for p in opts.basf_pars:
            try:
                name, value = p.split('=')
            except ValueError:
                msg = "Parameter `{}' supplied via `-p' option " + \
                    "is not in format NAME=VALUE"
                raise BadCommandLineError(msg.format(p), -3)
            
            basf_pars[name] = value

    opts.basf_pars = basf_pars

    if not opts.no_default_pars:
        if 'outpath_stub' not in opts.basf_pars:
            if len(mdst_files) > 1:
                msg = "Not exactly sure how to generate an output filename " + \
                    "from multiple input files."
                raise NotImplementedError(msg)
            else:
                opts.basf_pars['outpath_stub'] = \
                    os.path.basename(mdst_files[0]).rsplit('.', 1)[0]

        if 'inpath' not in opts.basf_pars:
            if len(mdst_files) > 1:
                msg = "Not sure how safe it is to insert " + \
                    "multiple filenames into `inpath'"
                raise NotImplementedError(msg)
            else:
                opts.basf_pars['inpath'] = mdst_files[0]           
        

    if opts.hbook:
        if 'HBOOK32768' not in os.environ:
            msg = 'Running an HBOOK-based module, ' + \
                'but HBOOK32768 variable is not set in environment'
            warnings.warn(msg)

        opts.hbook = \
            os.path.basename(mdst_files[0]).rsplit('.', 1)[0] + '.hbook'

        scrobj = BASFScript(basfmod, mdst_files, opts.basf_pars, 
                            opts.hbook, opts.nevents)

    if opts.write:
        with open(opts.write, 'w') as fp:
            fp.write(str(scrobj))
            
        return 0

    with tempfile.NamedTemporaryFile() as fp:
        fp.write(str(scrobj))
        fp.flush()

        basfpipe = subprocess.Popen(['basf', fp.name])

        basfpipe.communicate()

    return basfpipe.returncode

    

if __name__ == "__main__":
    import sys
    try:
        sys.exit(main())
    except BadCommandLineError, e:
        import os
        sys.stderr.write(str(e) + "\n")
        sys.stderr.write("See `{0} -h' for more.\n".format(os.path.basename(sys.argv[0])))
        sys.stderr.flush()
        sys.exit(e.retcode)
